import assert = require('node:assert');

type B = { name: string };
interface A extends B {
  name: string;
  setName<T extends string>(newName: T): asserts this is { name: T };
}
let a!: A;

a.setName('newName');
//   ^?
// !FAIL - DFA should be Current, can't be Interception. e.g. `void expression`)
// a.setName('111');

a.name;
//  ^?
// 只在当前作用域以及子作用域有效
{
  a.name
}
type _ = ReturnType<A['setName']>;
//   ^?

// # asserts Sth.
// via: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html

// with assertCond
function yell(str: any): string {
  assertsCond(typeof str === 'string');
  // @ts-expect-error - effect by asserts
  return str.toUppercase();
  //         ~~~~~~~~~~~
  // error: Property 'toUppercase' does not exist on type 'string'.
  //        Did you mean 'toUpperCase'?
}
function assertsCond(condition: any, msg?: string): asserts condition {
  if (!condition) {
    throw new assert.AssertionError({});
  }
}
